###############################################################################
# SuperLinks                                                                  #
# Copyright (c) 2000-2007 Greg Nolle (http://greg.nolle.co.uk)                #
###############################################################################
# This program is free software; you can redistribute it and/or modify it     #
# under the terms of the GNU General Public License as published by the Free  #
# Software Foundation; either version 2 of the License, or (at your option)   #
# any later version.                                                          #
#                                                                             #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       #
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for   #
# more details.                                                               ##                                                                             #
# You should have received a copy of the GNU General Public License along     #
# with this program; if not, write to the Free Software Foundation, Inc.,     #
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.                 #
###############################################################################
# ControlPanel/RestoreBackup.pm.pl -> RestoreBackup module                    #
###############################################################################
# DON'T EDIT BELOW UNLESS YOU KNOW WHAT YOU'RE DOING!                         #
###############################################################################
package CP::RestoreBackup;

BEGIN { require "System.pm.pl"; import System qw($SYSTEM); }
BEGIN { require "General.pm.pl"; import General qw($GENERAL); }
require "Error.pm.pl";
require "Standard.pm.pl";
require "Authenticate.pm.pl";
require "Logs.pm.pl";

use File::Path;
use File::Copy;
use File::Find;
use Cwd;
use Archive::Tar;
use strict;

require "ControlPanel/Output/RestoreBackup.pm.pl";

sub new {
  my ($class) = @_;
  my $self    = {};
  return bless($self, $class);
}

sub DESTROY { }

###############################################################################
# show subroutine
sub show {
  my $self = shift;
  my %in = (DB => undef, @_);

  #----------------------------------------------------------------------#
  # Authenticating...                                                    #
  
  &Authenticate::CP(DB => $in{'DB'}, ACTION => "BACKUPS_RESTORE");

  #----------------------------------------------------------------------#
  # Printing page...                                                     #

  my $Skin = Skin::CP::RestoreBackup->new();

  &Standard::PrintHTMLHeader();
  print $Skin->show();
  
  return 1;
}

###############################################################################
# do subroutine
sub do {
  my $self = shift;
  my %in = (DB => undef, @_);

  #----------------------------------------------------------------------#
  # Authenticating...                                                    #

  &Authenticate::CP(DB => $in{'DB'}, ACTION => "BACKUPS_RESTORE");

  #----------------------------------------------------------------------#
  # Checking fields...                                                   #

  if ($SL::QUERY{'BID'} eq "") {
    &Error::Error("CP", MESSAGE => "You didn't specify a Backup ID (BID)");
  }
  unless (-e "$SYSTEM->{'BACKUP_PATH'}/$SL::QUERY{'BID'}.log") {
    &Error::Error("CP", MESSAGE => "The Backup ID (BID) you specified is invalid");
  }

  #----------------------------------------------------------------------#
  # Preparing data...                                                    #

  my $Skin = Skin::CP::RestoreBackup->new();

  &Standard::PrintHTMLHeader();  

  unless ($SL::QUERY{'do'}) {
    print $Skin->do();
    return 1;
  }

  my $Log = Logs->new(PRINT => 1);
  
  my $Exit = eval {
    sub {
      $Log->Footer();
      exit;
    }
  };
  
  $Log->Header();

  $Log->Line("", "uplevel");
  $Log->Line("Beginning restore process.\n\n", "element");
  
  if (-e "$SYSTEM->{'BACKUP_PATH'}/$SL::QUERY{'BID'}.tar.gz") {
    $Log->Line("Unpacking $SL::QUERY{'BID'}.tar.gz... ", "element");
    my $tar = Archive::Tar->new();
       $tar->read("$SYSTEM->{'BACKUP_PATH'}/$SL::QUERY{'BID'}.tar.gz", 1);
    my $cwd = cwd();
    chdir($SYSTEM->{'BACKUP_PATH'});
    my @files = $tar->list_files();
    $tar->extract(@files);
    chdir($cwd);
    $Log->Line("Done.", "success");
  } elsif (-e "$SYSTEM->{'BACKUP_PATH'}/$SL::QUERY{'BID'}.tar") {
    $Log->Line("Unpacking $SL::QUERY{'BID'}.tar... ", "element");
    my $tar = Archive::Tar->new();
       $tar->read("$SYSTEM->{'BACKUP_PATH'}/$SL::QUERY{'BID'}.tar");
    my $cwd = cwd();
    chdir($SYSTEM->{'BACKUP_PATH'});
    my @files = $tar->list_files();
    $tar->extract(@files);
    chdir($cwd);
    $Log->Line("Done.", "success");
  }
  
  $Log->Line("Checking backup directory... ", "element");
  unless (-d "$SYSTEM->{'BACKUP_PATH'}/$SL::QUERY{'BID'}") {
    $Log->Line("Error: Directory not found", "error");
    &$Exit;
  }
  $Log->Line("Done.", "success");
  
  $Log->Line("Getting list of tables... ", "element");
  opendir(DIR, "$SYSTEM->{'BACKUP_PATH'}/$SL::QUERY{'BID'}");
  my @Tables;
  foreach my $file (grep(/\.cfg$/, readdir(DIR))) {
    $file =~ m/^(.*)\.cfg$/;
    push(@Tables, $1);
  }
  closedir(DIR);
  $Log->Line("Done.", "success");
  
  $Log->Line("Restoring tables...", "element");
  $Log->Line("", "uplevel");
  
  foreach my $table (@Tables) {
    next if ($table eq "LanguageSets" && !$SL::QUERY{'FORM_RESTORE_LANGUAGESETS'});
    next if ($table eq "Skins" && !$SL::QUERY{'FORM_RESTORE_SKINS'});
    next if ($table eq "StyleSheets" && !$SL::QUERY{'FORM_RESTORE_STYLESHEETS'});
    next if ($table eq "TemplateSets" && !$SL::QUERY{'FORM_RESTORE_TEMPLATESETS'});
    $Log->Line("Restoring \"$table\" table...", "element");
    $Log->Line("", "uplevel");
    
    $Log->Line("Dropping current table... ", "element");
    $in{'DB'}->DropTable(TABLE => $table) || ($Log->Line("Error: $in{'DB'}->{'ERROR'}", "error") and &$Exit);
    $Log->Line("Done.", "success");
    
    $Log->Line("Copying config file... ", "element");
    copy("$SYSTEM->{'BACKUP_PATH'}/$SL::QUERY{'BID'}/$table.cfg", "$SYSTEM->{'DB_PATH'}/$table.cfg")
      || ($Log->Line("Error: $!", "error") and &$Exit);
    $Log->Line("Done.", "success");
    
    $Log->Line("Reading data from backup... ", "element");
    open(EXPORT, "$SYSTEM->{'BACKUP_PATH'}/$SL::QUERY{'BID'}/$table/$table.export") || ($Log->Line("Error: $!", "error") and &$Exit);
    my @EXPORT = <EXPORT>;
    close(EXPORT);
    $Log->Line("Done.", "success");
    
    $Log->Line("Importing data... ", "element");
    (
      $in{'DB'}->Import(
        CFG     => "$SYSTEM->{'DB_PATH'}/$table.cfg",
        TABLE   => $table,
        CONTENT => \@EXPORT
      )
    ) || ($Log->Line("Error: $in{'DB'}->{'ERROR'}", "error") and &$Exit);
    $Log->Line("Done.", "success");

    $Log->Line("", "downlevel");
  }
  
  $Log->Line("", "downlevel");

  if (-e "$SYSTEM->{'BACKUP_PATH'}/$SL::QUERY{'BID'}/LanguageSets/Files" && $SL::QUERY{'FORM_RESTORE_LANGUAGESETS'}) {
    $Log->Line("Restoring language sets... ", "element");
    $Log->Line("", "uplevel");
    
    $Log->Line("Removing current language set files... ", "element");
    rmtree("$SL::PATH/Private/Skins/Language") || ($Log->Line("Error: $!", "error") and &$Exit);
    $Log->Line("Done.", "success");
    
    $Log->Line("Restoring backed-up language set files... ", "element");
    
    mkdir("$SL::PATH/Private/Skins/Language", 0777) || ($Log->Line("Error: $!", "error") and &$Exit);
    chmod(0777, "$SL::PATH/Private/Skins/Language");
    my $cwd = cwd();

    my (@files, @directories);
    my $findsub = eval {
      sub {
        if (-f) {
          push(@files, $File::Find::name);
        } elsif (-d && $_ !~ /^\.\.?$/) {
          push(@directories, $File::Find::name);
        }
      }
    };

    chdir("$SYSTEM->{'BACKUP_PATH'}/$SL::QUERY{'BID'}/LanguageSets/Files");
    find(\&$findsub, ".");
    chdir($cwd);

    foreach my $directory (sort @directories) {
      $directory =~ s/^\.\///;
      mkdir("$SL::PATH/Private/Skins/Language/$directory", 0777) || ($Log->Line("Error: $!", "error") and &$Exit);
      chmod(0777, "$SL::PATH/Private/Skins/Language/$directory");
    }
    foreach my $file (@files) {
      $file =~ s/^\.\///;
      copy("$SYSTEM->{'BACKUP_PATH'}/$SL::QUERY{'BID'}/LanguageSets/Files/$file", "$SL::PATH/Private/Skins/Language/$file") || ($Log->Line("Error: $!", "error") and &$Exit);
      chmod(0666, "$SL::PATH/Private/Skins/Language/$file");
    }
    
    $Log->Line("Done.", "success");
    $Log->Line("", "downlevel");
  }

  if (-e "$SYSTEM->{'BACKUP_PATH'}/$SL::QUERY{'BID'}/TemplateSets/Files" && $SL::QUERY{'FORM_RESTORE_TEMPLATESETS'}) {
    $Log->Line("Restoring template sets... ", "element");
    $Log->Line("", "uplevel");
    
    $Log->Line("Removing current template set files... ", "element");
    rmtree("$SL::PATH/Private/Skins/Templates") || ($Log->Line("Error: $!", "error") and &$Exit);
    $Log->Line("Done.", "success");
    
    $Log->Line("Restoring backed-up template set files... ", "element");
    
    mkdir("$SL::PATH/Private/Skins/Templates", 0777) || ($Log->Line("Error: $!", "error") and &$Exit);
    chmod(0777, "$SL::PATH/Private/Skins/Templates");
    my $cwd = cwd();

    my (@files, @directories);
    my $findsub = eval {
      sub {
        if (-f) {
          push(@files, $File::Find::name);
        } elsif (-d && $_ !~ /^\.\.?$/) {
          push(@directories, $File::Find::name);
        }
      }
    };

    chdir("$SYSTEM->{'BACKUP_PATH'}/$SL::QUERY{'BID'}/TemplateSets/Files");
    find(\&$findsub, ".");
    chdir($cwd);

    foreach my $directory (sort @directories) {
      $directory =~ s/^\.\///;
      mkdir("$SL::PATH/Private/Skins/Templates/$directory", 0777) || ($Log->Line("Error: $!", "error") and &$Exit);
      chmod(0777, "$SL::PATH/Private/Skins/Templates/$directory");
    }
    foreach my $file (@files) {
      $file =~ s/^\.\///;
      copy("$SYSTEM->{'BACKUP_PATH'}/$SL::QUERY{'BID'}/TemplateSets/Files/$file", "$SL::PATH/Private/Skins/Templates/$file") || ($Log->Line("Error: $!", "error") and &$Exit);
      chmod(0666, "$SL::PATH/Private/Skins/Templates/$file");
    }
    
    $Log->Line("Done.", "success");
    $Log->Line("", "downlevel");
  }

  if (-e "$SYSTEM->{'BACKUP_PATH'}/$SL::QUERY{'BID'}.tar.gz" || -e "$SYSTEM->{'BACKUP_PATH'}/$SL::QUERY{'BID'}.tar") {
    $Log->Line("Removing temporary directory... ", "element");
    if (rmtree("$SYSTEM->{'BACKUP_PATH'}/$SL::QUERY{'BID'}")) {
      $Log->Line("Done.", "success");
    } else {
      $Log->Line("Error: $!", "success");
    }
  }

  $Log->Line("\n\n", "");
  $Log->Line("All done!", "element");
  $Log->Line("", "downlevel");

  &$Exit;
}

1;